package org.beetl.sql.ext.jpa.mapper.template;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SqlId;
import org.beetl.sql.core.page.DefaultPageRequest;
import org.beetl.sql.core.page.DefaultPageResult;
import org.beetl.sql.core.page.PageRequest;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.mapper.builder.MethodParamsHolder;
import org.beetl.sql.mapper.builder.ReturnTypeParser;
import org.beetl.sql.mapper.template.PageTemplateMI;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

public class JpaDataPageTemplateMI extends PageTemplateMI{

	private final String countSql;
	private final MethodParamsHolder holder;
	private final boolean pageResultRequired;
//	private Class targetType;
	private ReturnTypeParser returnTypeParser;
	
	public JpaDataPageTemplateMI(String sql, ReturnTypeParser returnTypeParser, boolean pageResultRequired, MethodParamsHolder holder) {
		super(sql, returnTypeParser.getPageResultType(), pageResultRequired, holder);
		this.countSql=null;
		this.holder = holder;
		this.pageResultRequired = pageResultRequired;
		this.returnTypeParser = returnTypeParser;
	}
	
	public JpaDataPageTemplateMI(String sql, ReturnTypeParser returnTypeParser, boolean pageResultRequired, MethodParamsHolder holder,String countSql) {
		super(sql, returnTypeParser.getPageResultType(), pageResultRequired, holder);
		this.countSql=countSql;
		this.holder = holder;
		this.pageResultRequired = pageResultRequired;
		this.returnTypeParser = returnTypeParser;
	}
	
	@Override
    public Object call(SQLManager sm, Class entityClass, Method m, Object[] args) {
		Object pageArg = args[holder.getPageRequestIndex()];
		PageRequest pageRequest = null;
		Long count = null;
		boolean isEmpty = true;
		long totalPage = 0;
		Object newArgs = getParas(args);
		SqlId sqlId = getSqId(sm,entityClass,m);
		Pageable p = null;
		boolean isJpaResult = this.returnTypeParser.getType().isAssignableFrom(org.springframework.data.domain.Page.class);
		if(pageArg instanceof org.springframework.data.domain.PageRequest) {
			count = sm.execute(sqlId, countSql, Long.class, newArgs).get(0);//计算出总数
			org.springframework.data.domain.PageRequest opageArg = (org.springframework.data.domain.PageRequest)pageArg;
			isEmpty = count == null || count < 1;
			p = Pageable.ofSize(opageArg.getPageSize());
			if (isEmpty ) {
				if(isJpaResult) {
					return new PageImpl(new ArrayList(),p,0);
				}
				return DefaultPageRequest.of(opageArg.getPageNumber(), opageArg.getPageSize()).of(new ArrayList(), 0L);
			}
			totalPage = Math.toIntExact(count % opageArg.getPageSize() == 0 ? (count / opageArg.getPageSize()) : (count / opageArg.getPageSize() + 1));
			pageRequest = DefaultPageRequest.of(opageArg.getPageNumber(), opageArg.getPageSize(),false);
		}else {
			pageRequest = (PageRequest) pageArg;
		}
      //TODO 暂时不知道怎么搞这个分页

//		String pagesql = "select * from ( "+this.getSql()+ " ) a ";
//		List list = sm.execute(this.getSql(), this.targetType, newArgs, pageRequest.getStart(sm.isOffsetStartZero()), pageRequest.getPageSize());
//		if(!pageResultRequired) {
//			return list;
//		}
//		if(!isEmpty) {
//			return pageRequest.of(list, count);
//		}
//		return pageRequest.of(list);
		
        PageResult pageResult = sm.executePageQuery(sqlId,this.getSql(), this.returnTypeParser.getPageResultType(), newArgs, pageRequest);
        
        if(pageResult instanceof DefaultPageResult && !isEmpty && isJpaResult ) {
//			DefaultPageResult dpr = (DefaultPageResult)pageResult;
//			dpr.setTotalRow(count);
//			dpr.setTotalPage(totalPage);
//			pageResult= dpr;
        	return new PageImpl(pageResult.getList(),p,count);
		}
      
        if (pageResultRequired) {
            return pageResult;
        } else {
            return pageResult.getList();
        }
    }

}
